package com.example.edu;

/**
 * 访问者模式的基本想法如下：
 * 首先我们拥有一个由许多对象构成的对象结构，
 * 这些对象的类都拥有一个accept方法，用来接受访问者对象；
 * 访问者是一个接口，它拥有一个visit方法，这个方法对访问到的对象结构中不同类型的元素作出不同的反应；
 * 在对象结构的一次访问过程中，我们遍历整个对象结构，
 * 对每一个元素都实施accept方法，在每一个元素的accept方法中回调访问者的visit方法，
 * 从而使访问者得以处理对象结构的每一个元素。
 * 我们可以针对对象结构，设计不同的、实在的访问者类来完成不同的操作。
 * <p>
 * 实际应用：
 * <ul>
 *     <li>JDK的nio模块提供的 FileVisitor ，支持了递归遍历文件树</li>
 *     <li>
 *         抽象语法树（AST，abstract syntax tree），
 *         很多自定义标签内容，都可以抽象为一颗语法树，几乎每个AST都会涉及到访问者模式
 *         例如：
 *         jdk自带的TreeMaker；
 *         开源的JavaParser用于解析java文件的ast；
 *         freemarker解析ftl文件的ast，通过访问者模式计算表达式的内容；
 *         eclipse提供的开源包org.eclipse.jdt:org.eclipse.jdt.core:3.13.0(这个应该有，我没有过多的了解）；
 *     </li>
 *     <li>其他场景，参见school</li>
 * </ul>
 * <p>
 * 访问者模式包含五个要素：
 * <ul>
 *     <li>抽象-被访问者（Visitable），定义了accept方法，参数接收访问者</li>
 *     <li>实现-被访问者（VisitableImpl），实现抽象被访问者，accept方法体通常实现：Visitor.visit(this);</li>
 *     <li>
 *         抽象-访问者（Visitor），定义visit方法，参数接收被访问者实现类（缺点），抽象访问者的visit重载个数等于被访问者实现类个数（缺点），
 *         通过多态进行方法分派，实现方法调用
 *     </li>
 *     <li>实现-访问者（VisitorImpl），实现visit方法，真正操作被访问者的数据</li>
 *     <li>数据对象，维护被访问者的数据集合，并对外暴露方法，接收访问者，遍历被访问者数据集合，调用accept方法</li>
 * </ul>
 * <p>
 * 优点：
 * <ul>
 *     <li>解耦数据结构与数据操作</li>
 *     <li>对访问者扩展性较好</li>
 * </ul>
 * <p>
 * 缺点：
 * <ul>
 *     <li>一旦新增被访问者，意味着访问者必须增加对应的visit重载，违背了开闭原则</li>
 *     <li>访问者的visit依赖了具体实现，违背了依赖倒置原则</li>
 *     <li>修改被访问者时，可能会大面积修改相应的访问者</li>
 * </ul>
 *
 */
public class Main {

    public static void main(String[] args) {
    }

}
